package cn.lg.soar.common.model;

/**
 * 状态机接口
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface StateMachine<S> {

    /**
     * 允许的来源状态（只有这些状态下允许执行事件）
     * @return
     */
    S[] getSource();

    /**
     * 事件执行后的目标状态（事件执行成功后，状态流转到此状态）
     * @return
     */
    S getTarget();

    /**
     * 执行事件（事件允许执行后返回状态值，不被允许执行走拒绝处理，抛异常）
     * @param current 当前状态
     * @return 目标状态
     */
    default S execute(S current) {
        if (allowable(current)) {
            return getTarget();
        }
        return reject(current);
    }

    /**
     * 判断当前状态是否允许执行事件
     * @param current 当前状态
     * @return
     */
    default boolean allowable(S current) {
        S[] source = getSource();
        if (source == null || source.length == 0) {
            return true;
        }
        for (S s : source) {
            if (s.equals(current)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 被拒绝后的处理（当前状态不满足来源状态时）
     * @param current 当前状态
     * @return
     */
    default S reject(S current) {
        throw new StateException(current + "无法流转到" + getTarget());
    }

    public static class StateException extends RuntimeException{
        public StateException() {
            super();
        }

        public StateException(String message) {
            super(message);
        }

        public StateException(String message, Throwable cause) {
            super(message, cause);
        }

        public StateException(Throwable cause) {
            super(cause);
        }

        protected StateException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    }
}
